<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    a {
      position: absolute;
      left: 200px;
      top: 200px;
      width: 100px;
      height: 100px;
      background-color: lightblue;
    }

    div {
      display: none;
      position: absolute;
      left: 0;
      top: 0;
      width: 100px;
      height: 200px;
      background-color: lightcoral;
    }
  </style>
</head>
<body>
<a href="javascript:void(0)"></a>
<div></div>
<script>

function getViewportSize() {
  if(window.innerWidth) {
    return {
      width: window.innerWidth,
      height: window.innerHeight
    }
  }else {
    // 如果是IE的怪异模式
    if(document.compatMode === 'BackCompat') {
      return {
        width: document.body.clientWidth,
        height: document.body.clientHeight
      }
    // 是标准模式 CSS1Compat
    }else {
      return {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      }
    }
  }
}

function pagePos(e) {
  var sLeft = getScrollOffset().left, // x轴的滚动距离
      sTop = getScrollOffset().top, // y轴的滚动距离
      cLeft = document.documentElement.clientLeft || 0, // 文档x轴偏移距离
      cTop = document.documentElement.clientTop || 0; // 文档y轴偏移距离

  return {
    x: e.clientX + sLeft - cLeft,
    y: e.clientY + sTop - cTop
  }
}

function getScrollOffset() {
  if(window.pageXOffset) { // 该方法在IE9以下不支持
    console.log(window.pageXOffset,window.pageYOffset);
    return {
      left: window.pageXOffset,
      top: window.pageYOffset
    }
  }else {
    return { // 在chrome中他俩必定有一个为0，所以就相加
      left: document.body.scrollLeft + document.documentElement.scrollLeft,
      top: document.body.scrollTop + document.documentElement.scrollTop
    }
  }
}

function getStyles(elem, prop) {
  if(window.getComputedStyle) {
    if(prop) {
      return window.getComputedStyle(elem)[prop];
    }else {
      return window.getComputedStyle(elem);
    }
  }else {
    if(prop) {
      return elem.currentStyle[prop];
    }else {
      return elem.currentStyle;
    }
  }
}

function addEvent(el, type, fn) {
  if(el.addEventListener) {
    el.addEventListener(type, fn, false);
  }else if(el.attachEvent) {
    // IE中的attachEvent接收的事件类型前加 'on'
    // fn中的this指向window
    el.attachEvent('on' + type, function() {
      fn.call(el);
    });
  }else {
    // 兼容性最好的句柄事件处理函数
    el['on' + type] = fn;
  }
}

function removeEvent(el, type, fn) {
  if(el.addEventListener) {
    el.removeEventListener(type, fn, false);
  }else if(el.attachEvent) {
    // IE中的attachEvent接收的事件类型前加 'on'
    // fn中的this指向window
    el.detachEvent('on' + type, fn);
  }else {
    // 兼容性最好的句柄事件处理函数
    el['on' + type] = null;
  }
}

function preventDefaultEvent(e) {
  var e = e || window.event;

  if(e.preventDefault) {
    e.preventDefault();
  }else {
    // IE 写法
    e.returnValue = false;
  }
}

function cancelBubble(e) {
  var e = e || window.event;

  if(e.stopPropagation) {
    e.stopPropagation();
  }else {
    // IE 写法
    e.cancelBubble = true;
  }
}

</script>
<script>
  Element.prototype.dragNclick = (function(elemClick) {

    var oPos = [], // 保存元素的宽度、高度
        bTime = 0, 
        eTime = 0,
        cbTime = 0, // 第一次点击的时间
        ceTime = 0, // 第二次点击的时间
        counter = 0, // 计数器
        t = null, // 定时器
        wWidth = getViewportSize().width, // 网页的宽
        wHeight = getViewportSize().height, // 网页的高
        elemWidth = parseInt(getStyles(this, 'width')), // 元素的宽
        elemHeight = parseInt(getStyles(this, 'height')), // 元素的高
        mWidth = parseInt(getStyles(menu, 'width')), // 菜单的宽
        mHeight = parseInt(getStyles(menu, 'height')); // 菜单的高

    console.log('wW', wWidth);
    console.log('wH', wHeight);
    console.log('elemW', elemWidth);
    console.log('elemH', elemHeight);

    elemDrag.call(this);

    function elemDrag() {
      var x, // 点击点到元素边缘的x距离
          y, // 点击点到元素边缘的y距离
        _self = this;

      addEvent(this, 'mousedown', function(e) {
        var e = e || window.event,
            btnCode = e.button;

        if(btnCode === 2) {
          // 右键
          var mLeft = pagePos(e).x, //点击点的左偏移值
              mTop = pagePos(e).y; // 点击点的上偏移值

          // 菜单在右侧的时候，显示位置改变
          if(mLeft <= 0) {
            mLeft = 0;
          }else if(mLeft >= wWidth - mWidth) {
            mLeft -= mWidth;
          }

          // 菜单在底部的时候，显示位置改变
          if(mTop <= 0) {
            mTop = 0;
          }else if(mTop >= wHeight - mHeight) {
            mTop -= mHeight;
          }

          menu.style.left = mLeft + 'px';
          menu.style.top = mTop + 'px';
          menu.style.display = 'block';

        }else if(btnCode === 0) {
          // 左键
          bTime = new Date().getTime();
          oPos = [getStyles(_self, 'left'), getStyles(_self, 'top')];

          console.log(_self);
          // x = PageX - elem.left
          x = pagePos(e).x - parseInt(getStyles(_self, 'left'));
          y = pagePos(e).y - parseInt(getStyles(_self, 'top'));

          console.log('x,y', x, y);

          addEvent(document, 'mousemove', mouseMove);
          addEvent(document, 'mouseup', mouseUp);

          // 阻止事件冒泡跟默认事件
          cancelBubble(e);
          preventDefaultEvent(e);
        }

      });

      addEvent(document, 'contextmenu', function(e) {
        var e = e || window.event;
        // 阻止鼠标右键默认菜单事件
        preventDefaultEvent(e);
      });

      addEvent(document, 'click', function(e) {
        menu.style.display = 'none';
      });

      addEvent(menu, 'click', function(e) {
        var e = e || window.event;

        // 阻止冒泡
        cancelBubble(e);
      });

      function mouseMove(e) {
        var e = e || window.event,
            elemLeft = pagePos(e).x - x, // 元素的left偏移值
            elemTop = pagePos(e).y - y // 元素的top偏移值

        // console.log('elemL', elemLeft);
        // console.log('elemT', elemTop);

        menu.style.display = 'none';

        // 判断元素边界
        // 判断左右侧
        if(elemLeft <= 0) {
          elemLeft = 0;
          console.log('0了');
        }else if(elemLeft >= wWidth - elemWidth) {
          console.log('边缘了');
          elemLeft = wWidth - elemWidth;
          // 考虑到滚动条问题，开发中通常 - 1
          // elemLeft = wWidth - elemWidth - 1;
        }

        // 判断顶底侧
        if(elemTop <= 0) {
          elemTop = 0;
        }else if(elemTop >= wHeight - elemHeight) {
          elemTop = wHeight - elemHeight;
          // elemTop = wHeight - elemHeight - 1;
        }

        _self.style.left = elemLeft + 'px';
        _self.style.top = elemTop + 'px';
      }

      function mouseUp(e) {
        var e = e || window.event;

        eTime = new Date().getTime();

        if(eTime - bTime < 100) {
          _self.style.left = oPos[0] + 'px';
          _self.style.top = oPos[1] + 'px';

          counter ++;

          if(counter === 1) {
            cbTime = new Date().getTime();
          }

          if(counter === 2) {
            ceTime = new Date().getTime();
          }

          if(cbTime && ceTime && (ceTime - cbTime < 200)) {
            elemClick();
          }

          t = setTimeout(function() {
            cbTime = 0;
            ceTime = 0;
            counter = 0;
            clearTimeout(t);
          }, 200);

        }
        removeEvent(document, 'mousemove', mouseMove);
        removeEvent(document, 'mouseup', mouseUp);
      }
    }

  });
</script>
<script>
var oLink = document.getElementsByTagName('a')[0],
    menu = document.getElementsByTagName('div')[0];

oLink.dragNclick(function() {
  window.open('http://www.baidu.com');
});
</script>
</body>
</html>